"""
    Email service
"""

import email
import poplib
from bs4 import BeautifulSoup
from email.parser import Parser
from email.message import Message


def get_all_msg(mail_user, mail_pass, pop3_server):
    """
    获取所有邮件消息
    :return: message list
    """
    server = poplib.POP3(pop3_server)  # 连接到服务器

    # 身份验证
    server.user(mail_user)
    server.pass_(mail_pass)

    all_msg = []
    for r in range(1, len(server.list()[1]) + 1):
        resp, msg_lines, msg_size = server.retr(r)  # ['response', ['line', ...], octets]]]
        msg_content = b'\r\n'.join(msg_lines).decode('utf-8', "ignore")
        all_msg.append(Parser().parsestr(text=msg_content))

    server.close()

    return all_msg


def parse_subject(msg: Message) -> str:
    """
    解析邮件主题
    :param msg: Message
    :return: subject
    """
    subject, charset = email.header.decode_header(msg.get('subject'))[0]
    return subject.decode(charset) if charset else subject


def parse_address(msg: Message) -> tuple:
    """
    解析邮件来源
    :param msg: Message
    :return: from
    """
    hdr, addr = email.utils.parseaddr(msg.get('from'))
    name, charset = email.header.decode_header(hdr)[0]
    return name.decode(charset) if charset else name, addr


def parse_content(msg: Message):
    """
    解析邮件正文
    :param msg: Message
    :return: content
    """
    for part in msg.walk():
        if not part.is_multipart():
            return part.get_payload(decode=True).decode(encoding=part.get_content_charset())

    return None


def uoh_mail_service(subject, username, password, server):
    """
    红河学院邮件服务
    :param server: 服务器地址
    :param password: 邮箱授权密码
    :param username: 邮箱用户名
    :param subject: 收取主题
    :return: [[(name, address), [name, student_num, password]], ...]
    """
    sources = []
    for msg in get_all_msg(username, password, server):
        if parse_subject(msg) == subject:
            addr = parse_address(msg)
            cont = BeautifulSoup(parse_content(msg), 'lxml').get_text(strip=True)
            sources.append([addr, list(filter(lambda x: x != '', map(lambda x: x.strip(), cont.split(' '))))])

    return sources
